#include"main.h"
/*#define ERR_VFS_CREATE_00 "VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_CREATE_01 "DATA_FILE_ALREADY_EXISTS"
#define ERR_VFS_CREATE_02 "CANNOT_CREATE_DATAFILE"
// The slash (/) character is not allowed
#define ERR_VFS_CREATE_03 "INVALID_CHARACTER_IN_NAME"
// Valid range for size is 1 to 1024 (inclusive)
#define ERR_VFS_CREATE_04 "INVALID_SIZE"
//New   (If label name exceeds 30 characters)
#define ERR_VFS_CREATE_05 "VFS_LABEL_TOO_LARGE" */
int createprjct(char name[filename_size],int size)
{
   struct MainHeader header_local;
char *freelist_local;
struct FileDescriptor *file_descriptors_local;

   if(strlen(name)==0 || size==0)
   {
       printf("createvfs_FAILURE %s\n",ERR_VFS_CREATE_00);//insufficient arguments
        return 0;
   }

FILE *fp;
    fp=NULL;
    if(access(name, F_OK)==0)
    {
        printf("createvfs_FAILURE %s\n",ERR_VFS_CREATE_01);//file already exists
        return 0;
    }
if(size<1 || size>1024)
    {
        printf("createvfs_FAILURE %s\n",ERR_VFS_CREATE_04);//invalid size
        return 0;
    }
   if(strlen(name)>30)
   {
       printf("createvfs_FAILURE %s\n",ERR_VFS_CREATE_05);//vfs label too large
        return 0;
   }


    int length=0;
    while(length<strlen(name))
    {
        if(name[length]=='/')
        {
            printf("createvfs_FAILURE %s\n",ERR_VFS_CREATE_03);//invalid name
            return 0;
        }
        length++;
    }



    strcpy(header_local.file_sys_label,name);
    header_local.MAX_FILE_DESCRIPTORS=(size/((blocksize/1024)));// this wont hold true if you cange the block size size*1024/size of block in bytes
    header_local.used_file_descriptors=0;
    freelist_local=(char *)malloc(header_local.MAX_FILE_DESCRIPTORS*sizeof(char));
    file_descriptors_local=(struct FileDescriptor *)malloc(header_local.MAX_FILE_DESCRIPTORS*sizeof(struct FileDescriptor));
    int p;
    for(p=0; p<header_local.MAX_FILE_DESCRIPTORS; p++)
    {
        freelist_local[p]=0;
        file_descriptors_local[p].locationblocknumber=p;
    }


    fp=NULL;
    fp=fopen(name, "wb"); //open file in binary write mode
    if(fp==NULL)
    {
        printf("createvfs_FAILURE %s\n",ERR_VFS_CREATE_02);//cannot create datafile
        return 0;
    }


    fwrite(&header_local,sizeof(struct MainHeader),1,fp);
    fwrite(freelist_local,(header_local.MAX_FILE_DESCRIPTORS*sizeof(char)),1,fp);
    fwrite(file_descriptors_local,(header_local.MAX_FILE_DESCRIPTORS*sizeof(struct FileDescriptor)),1,fp);
    fseek(fp,(header_local.MAX_FILE_DESCRIPTORS*sizeof(struct Block)),SEEK_CUR);//reaching at the end of size

    fputc(EOF,fp);
    fclose(fp);
    free(freelist_local);
    free(file_descriptors_local);

    printf("createvfs_SUCCESS\n");

    return 1;





}




/*#define ERR_VFS_MOUNT_00 "VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_MOUNT_01 "DATA_FILE_NOT_FOUND"
#define ERR_VFS_MOUNT_02 "CANNOT_READ_FROM_FILE"
//New
#define ERR_VFS_MOUNT_03 "VFS_ALREADY_MOUNTED"*/
int mountprjct(char name[filename_size])
{
    if(strlen(name)==0)
    {
        printf("mountvfs_FAILURE %s\n",ERR_VFS_MOUNT_00);//insufficient arguments
        return 0;

    }
   /* if(access(name, F_OK)!=0)
    {
        printf("\nmountvfs_FAILURE %s",ERR_VFS_MOUNT_01);//file not found
        return 0;
    }*/
    int p=0;
    if(strcmp(mountstate,"")!=0)
    {
        printf("mountvfs_FAILURE %s\n",ERR_VFS_MOUNT_03);//mounted already
        return 0;

    }



    FILE *fp=NULL;
    fp=fopen(name,"rb");
    if(fp==NULL)
    {
        printf("mountvfs_FAILURE %s\n",ERR_VFS_MOUNT_02);//cannot read
        return 0;
    }


    fread(&header,sizeof(struct MainHeader),1,fp);

    freelist=(char *)malloc(header.MAX_FILE_DESCRIPTORS*sizeof(char));
    fread(freelist,(header.MAX_FILE_DESCRIPTORS*sizeof(char)),1,fp);
    file_descriptors=(struct FileDescriptor *)malloc(header.MAX_FILE_DESCRIPTORS*sizeof(struct FileDescriptor));
    fread(file_descriptors,(header.MAX_FILE_DESCRIPTORS*sizeof(struct FileDescriptor)),1,fp);
    fclose(fp);

    //printf("used-%d",header.used_file_descriptors);
    struct FileDescriptor *fdd;
    fdd=(struct FileDescriptor *)malloc(sizeof(struct FileDescriptor));
    strcpy(fdd->locationfullpath,"/");
    strcpy(fdd->filename,"/");
    strcpy(fdd->filetype,"root");
    fdd->locationblocknumber=-1;
    fdd->filesize=0;

    int y=createroot(fdd);//root of n-ary tree
    //call initialise function of hashtable to set it to null
    initialiseHashTable();
    insert_Into_HashTable(fdd);
    //call initialise function of BST
    initialize_BST();
    //if (y==0) return 0;
    int i;
    for(i=0; i<(header.MAX_FILE_DESCRIPTORS); i++)
    {


        if(freelist[i]!=0)
        {
            struct FileDescriptor *fd;
            fd=&file_descriptors[i];
            //inserting into nary

            insert(fd);

            //inserting into HashTable
           insert_Into_HashTable(fd);
            //call insert into bst

            insert_node(fd);
        }


    }
   strcpy(mountstate,name);
    printf("mountvfs_SUCCESS\n");
    return 1;

}




/*#define ERR_VFS_UNMOUNT_00 "VFS_INSUFFICIENT_ARGUMENTS"
// Use when fopen fails
#define ERR_VFS_UNMOUNT_01 "DATA_FILE_NOT_FOUND"
// Use when fwrite fails
#define ERR_VFS_UNMOUNT_02 "CANNOT_WRITE_TO_FILE"
//New
#define ERR_VFS_UNMOUNT_03 "VFS_NOT_MOUNTED"*/
int unmountprjct(char name[filename_size])
{
    if(strlen(name)==0)
    {
        printf("unmountvfs_FAILURE %s\n",ERR_VFS_UNMOUNT_00);//insufficient arguments
        return 0;
    }


    if(strcmp(mountstate,name)!=0)
    {
        printf("unmountvfs_FAILURE %s\n",ERR_VFS_UNMOUNT_03);//access denied, or not yet mounted
        return 0;
    }
    if(access(name, F_OK)!=0)
    {
        printf("unmountvfs_FAILURE %s\n",ERR_VFS_UNMOUNT_01);//file not found
        return 0;
    }
    FILE *fp=NULL;
    fp=fopen(name,"rb+");
    if(fp==NULL)
    {
        printf("unmountvfs_FAILURE %s\n",ERR_VFS_UNMOUNT_02);//cannot write
        return 0;
    }


    fwrite(&header,sizeof(struct MainHeader),1,fp);

    fwrite(freelist,((header.MAX_FILE_DESCRIPTORS)*sizeof(char)),1,fp);
    fwrite(file_descriptors,(header.MAX_FILE_DESCRIPTORS*sizeof(struct FileDescriptor)),1,fp);

    fclose(fp);
    free(freelist);
    free(file_descriptors);
    printf("unmountvfs_SUCCESS\n");
    strcpy(mountstate,"");
    return 1;
}

//used for insering into n-ary tree during mount operation
int insert(struct FileDescriptor *fd)
{
    char dir[locationpath_size];
    int q=0,j=0,y=0;
    dir[q]=fd->locationfullpath[q];//for '/'
    q++;
    while(q<strlen(fd->locationfullpath))//****************** dont you feel you need to reset the
    {


        while(fd->locationfullpath[q]!='/' && q<strlen(fd->locationfullpath))
        {
            dir[q]=fd->locationfullpath[q];
            q++;
        }
        dir[q]='\0';

        y=search_nary(dir);
        if(y==0)
        {
            if(q==strlen(fd->locationfullpath))//only this node/fd needs to be created
            {

                j=insert_nary(fd);//n-ary insert

            }
            else//intermediate nodes/fds also need to be created
            {
                struct FileDescriptor *fd1;
                fd1=(struct FileDescriptor *)malloc(sizeof(struct FileDescriptor));
                strcpy(fd1->locationfullpath,dir);
                strcpy(fd1->filetype,"dummy");
                j=insert_nary(fd1);
            }
        }
        else if(y==1 && q==strlen(fd->locationfullpath))
        {

            update_nary(fd);
        }
        if(fd->locationfullpath[q]=='/')
        {
            dir[q]=fd->locationfullpath[q];
            q++;
        }



    }

    if(j==1 || y==1) return 1;
    else if(j!=1 && y!=1) return 0;
}

int freedescriptor()
{
    if(header.used_file_descriptors<header.MAX_FILE_DESCRIPTORS)
    {
        int n;
        for(n=0; n<header.MAX_FILE_DESCRIPTORS; n++)
        {
            if(freelist[n]==0)
            {
                return n;
            }
        }

    }
    return -1;
}
